package dk.au.transxor.mote;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;

import net.tinyos.message.Message;
import net.tinyos.message.MessageListener;
import dk.au.transxor.message.IMessage;

public class FileReceiver implements MessageListener {

	private OutputStream fileInfo;
	private int totalFileBytes;
	private int currentReceivedBytes;
	private short sequenceId;
	private MoteUart moteUart;
	private Message messageType;
	private int maxDataLength;
	private MessageListener listener;
	

	public FileReceiver(IMessage messageType, int maxDataLength, MoteUart moteUart) throws FileNotFoundException {
		this.maxDataLength = maxDataLength;
		this.moteUart = moteUart;
		this.messageType = (Message) messageType;
		listener = null;
		
	}
	
	public FileReceiver(IMessage messageType, int maxDataLength, MoteUart moteUart, MessageListener listener) throws FileNotFoundException {
		this(messageType, maxDataLength, moteUart);
		this.listener = listener;
		
	}
	
	public void receiveFile(File file) throws FileNotFoundException {
		
		
		if(!file.exists()) {
			try {
				
				file.createNewFile();
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		stop();
		this.currentReceivedBytes = 0;
		this.totalFileBytes = 0;
		this.sequenceId = 1;
		
		fileInfo = new BufferedOutputStream(new FileOutputStream(file));
		moteUart.addMessageListener(messageType, this);
		
	}
	
	private synchronized void stop() {

		try
		{
			
			moteUart.removeMessageListener(messageType, this);
			
		} catch(IllegalArgumentException e) {
		}
		
		if(fileInfo != null) {
			try {
				
				fileInfo.flush();
				fileInfo.close();
				
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			fileInfo = null;
		}
	}

	@Override
	public void messageReceived(int to, Message m) {

		if (m != null) {
			
			IMessage message = (IMessage) m;
			//System.out.println(" RAW - Seq:" + sequenceId + " - " + new String(message.get_data_field()));
			
			if(listener != null)
				listener.messageReceived(to, m);

			try {

					if (sequenceId == message.get_data_seq()) {
						
						if(sequenceId == 1) {
							
							ByteBuffer byteBuffer = ByteBuffer.wrap(message.get_data_field());
							currentReceivedBytes = 0;
							totalFileBytes = byteBuffer.getInt();
							System.out.println(String.format("Receive FileSize: %s (0x%s) bytes", totalFileBytes, Integer.toHexString(totalFileBytes)));
							
						}
						else {
							
							if(totalFileBytes - currentReceivedBytes >= maxDataLength)
								fileInfo.write(message.get_data_field(), 0, maxDataLength);
							else
								fileInfo.write(message.get_data_field(), 0, totalFileBytes - currentReceivedBytes);
							
							currentReceivedBytes += maxDataLength;
							fileInfo.flush();
							
							if(currentReceivedBytes >= totalFileBytes) { 
								stop();
								System.out.println("File received");
							}
							
						}
						
						sequenceId++;
					}
					else {
						System.out.println("Sequence out of order! " + message.get_data_seq());
					}

			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}